#ifndef RAY_CU
#define RAY_CU
#include "Ray.h"


__host__ __device__  Vector3 Ray::follow(float tVal) const {
    Vector3 point = origin + (direction * tVal);
    return point;
}

__host__ __device__  Ray Ray::reflect(const Vector3& normal, const Vector3& hitPoint) const{
    //copy this ray
    Ray reflectedRay(*this);
    //reflect from point of intersection
    reflectedRay.origin = hitPoint;
    //calculate the new direction
    float c = -direction.dot(normal);
    reflectedRay.direction = direction + (normal*(2*c));
    reflectedRay.direction.normalize();
    
    return reflectedRay;
}

__host__ __device__  Ray Ray::refract(const Vector3& normal, const Vector3& hitPoint, float newRefractiveIndex) const {
    //copy this ray as a starting point
    Ray refractedRay(*this);
    //refract from point of intersection
    refractedRay.origin = hitPoint;
    //calculate the new direction
    float n = 1.0f/newRefractiveIndex;
    //if leaving the shape, flip the normal and the IoR's
    Vector3 adjustedNormal(normal);
    if(normal.dot(direction) > 0){
        n = 1.0f/n;
        adjustedNormal *= -1.0;
    }
    float c1 = adjustedNormal.dot(direction) * -1.0f;
    float c2 = 1.0f - ((1.0f - (c1 * c1))*(n*n));
    if(c2 < 0.0f) //c2 is never < 0
    {
        //TIR. Return the reflected ray 
        return reflect(hitPoint, adjustedNormal);
    }
    refractedRay.direction = (direction * n) + adjustedNormal * ((n*c1) - sqrt(c2));
    refractedRay.direction.normalize();
    return refractedRay;
}

#endif
